package com.iwith.dongmoon.activity;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;

import com.iwith.dongmoon.gsonlist.BizList;
import com.iwith.dongmoon.gsonlist.MemberList;
import com.iwith.dongmoon.gsonlist.MemberListItem;
import com.iwith.dongmoon.listadpater.FindListAdapter;
import com.iwith.dongmoon.util.RequestGson;
import com.iwith.dongmoon.util.ResultCode;
import com.iwith.dongmoon.util.SessionManager;
import com.iwith.dongmoon.util.ThreadInterface;
import com.iwith.dongmoon.util.ThreadTask;
import com.nhn.android.maps.NMapActivity;
import com.nhn.android.maps.NMapController;
import com.nhn.android.maps.NMapLocationManager;
import com.nhn.android.maps.NMapLocationManager.OnLocationChangeListener;
import com.nhn.android.maps.NMapOverlay;
import com.nhn.android.maps.NMapOverlayItem;
import com.nhn.android.maps.NMapView;
import com.nhn.android.maps.NMapView.LayoutParams;
import com.nhn.android.maps.NMapView.OnMapStateChangeListener;
import com.nhn.android.maps.NMapView.OnMapViewDelegate;
import com.nhn.android.maps.maplib.NGeoPoint;
import com.nhn.android.maps.nmapmodel.NMapError;
import com.nhn.android.maps.overlay.NMapPOIdata;
import com.nhn.android.maps.overlay.NMapPOIitem;
import com.nhn.android.mapviewer.NMapPOIflagType;
import com.nhn.android.mapviewer.NMapViewerResourceProvider;
import com.nhn.android.mapviewer.overlay.NMapCalloutCustomOverlay;
import com.nhn.android.mapviewer.overlay.NMapCalloutOverlay;
import com.nhn.android.mapviewer.overlay.NMapMyLocationOverlay;
import com.nhn.android.mapviewer.overlay.NMapOverlayManager;
import com.nhn.android.mapviewer.overlay.NMapOverlayManager.OnCalloutOverlayListener;
import com.nhn.android.mapviewer.overlay.NMapPOIdataOverlay;
import com.nhn.android.mapviewer.overlay.NMapPOIdataOverlay.OnStateChangeListener;

public class Tab_FindActivity extends NMapActivity implements
		OnItemSelectedListener, OnClickListener, OnMapStateChangeListener, OnLocationChangeListener, OnCalloutOverlayListener, OnStateChangeListener, OnMapViewDelegate{
	// for logging
	private static final String LOG_TAG = "Tab_FindActivity";
	// private static final boolean DEBUG = true;

	// if the location source is not enabled, we can use the location of Sorabol
	// high school by default

	// map API용 변수들
	private final String API_KEY = "c694d8ccd10a3744d20c1478d8885c2b";
	private final NGeoPoint NMAP_LOCATION_DEFAULT = new NGeoPoint(127.0758264, 37.6453984);
	public int mZoomLevel = 11;
	public int mViewMode = NMapView.VIEW_MODE_VECTOR;
	public boolean mTrafficMode = false;
	public boolean mBicycleMode = false;

	// for setting maps
	private NMapView mMapView;
	private NMapController mMapController;
	private NMapLocationManager mMapLocationManager;
	private NMapOverlayManager mOverlayManager;
	private NMapMyLocationOverlay mMyLocationOverlay;
	private NMapViewerResourceProvider mMapViewerResourceProvider;

	// for get userid
	private String userid;
	private SessionManager mSessionManager = null;


	// for spinner
	private Spinner rangeSpinner;
	private Spinner biztypeSpinner;
	private Integer rangeSpinnerPosition = 0;
	private Integer biztypeSpinnerPosition = 0;
	
	// for UI
	private Integer toggleFlag = ResultCode.TOGGLE_MAP;
	private ListView aroundList;
	private Button toggleListMapBt;
	private Context mContext;

	// for communicating with server
	private RequestGson requestGson = new RequestGson();
	private MemberList memberList;

	/** Called when the activity is first created. */
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.tab_find);
		mSessionManager = new SessionManager(this);
		mContext = this;

		setMaps();
		setSpinner();
	}

	@Override
	public void onResume() {
		super.onResume();
		ThreadTask.onFinishAll();
		startMyLocation();
		Initialize();
	}

	@Override
	public void onPause() {
		super.onPause();
		stopMyLocation();
		ThreadTask.onFinishAll();
		overridePendingTransition(0, 0);
	}
	
	private void setSpinner() {
		biztypeSpinner = (Spinner) findViewById(R.id.tabfind_biztypespinner);
		rangeSpinner = (Spinner) findViewById(R.id.tabfind_rangespinner);
		aroundList = (ListView) findViewById(R.id.tabfind_listview);
		ThreadInterface threadInterface = new ThreadInterface() {
			BizList bizList;
			public void onThread() {
				bizList = requestGson.getBizGsonBySendingAPI(mContext, "/businessType", "GET", "");
			}

			public void onThreadEnd() {
				ArrayList<String> biztypeStringList = new ArrayList<String>();

				biztypeStringList.add("전체");
				for (int i = 1; i < bizList.getItemCount(); i++) {
					biztypeStringList.add(bizList.getList().get(i).getType_name());
				}

				ArrayAdapter<String> biztypeAdapter = new ArrayAdapter<String>(mContext, android.R.layout.simple_spinner_item, biztypeStringList);
				biztypeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
				biztypeSpinner.setAdapter(biztypeAdapter);
				biztypeSpinner.setSelection(biztypeSpinnerPosition); // 현재 선택지 선택;

				ArrayAdapter<CharSequence> rangeAdapter = ArrayAdapter.createFromResource(mContext, R.array.rangeString, android.R.layout.simple_spinner_item);
				rangeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
				rangeSpinner.setAdapter(rangeAdapter);
				rangeSpinner.setSelection(rangeSpinnerPosition);
			}
		};
		ThreadTask task = new ThreadTask((Activity) mContext, threadInterface);
		task.execute();

		biztypeSpinner.setOnItemSelectedListener(this);
		rangeSpinner.setOnItemSelectedListener(this);
	}

	private void setMaps() {
		mMapView = (NMapView) findViewById(R.id.tabfind_nmv);
		mMapView.setApiKey(API_KEY);

		// initialize map view
		mMapView.setClickable(true);
		mMapView.setEnabled(true);
		mMapView.setFocusable(true);
		mMapView.setFocusableInTouchMode(true);
		mMapView.requestFocus();

		// register listener for map state changes
		mMapView.setOnMapStateChangeListener(this);
//		mMapView.setOnMapViewDelegate(this);

		// use map controller to zoom in/out, pan and set map center, zoom level
		mMapController = mMapView.getMapController();

		// use built in zoom controls
		NMapView.LayoutParams lp = new NMapView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, NMapView.LayoutParams.BOTTOM_RIGHT);
		mMapView.setBuiltInZoomControls(true, lp);

		// // set map controller state
		mMapController.setMapViewMode(mViewMode);
		mMapController.setMapViewTrafficMode(mTrafficMode);
		mMapController.setMapViewBicycleMode(mBicycleMode);
		mMapController.setMapCenter(NMAP_LOCATION_DEFAULT, mZoomLevel);
		//
		// location manager
		mMapLocationManager = new NMapLocationManager(this);
		mMapLocationManager.setOnLocationChangeListener(this);

		// // create resource provider
		mMapViewerResourceProvider = new NMapViewerResourceProvider(this);

		// create overlay manager
		mOverlayManager = new NMapOverlayManager(this, mMapView, mMapViewerResourceProvider);
		// register callout overlay listener to customize it.
		mOverlayManager.setOnCalloutOverlayListener(this);//
	
		// // create my location overlay
		mMyLocationOverlay = mOverlayManager.createMyLocationOverlay(mMapLocationManager, null);
	}
	
	private void setAroundList(){
		ThreadInterface threadInterface = new ThreadInterface(){
			public void onThread() {
				NGeoPoint mylocation = mMapLocationManager.getMyLocation();
				if(mylocation!=null){
					Double latitude = mylocation.getLatitude();
					Double longitude = mylocation.getLongitude();
					String bizType = biztypeSpinner.getSelectedItem().toString().replace(" ", "%20");
					String range = rangeSpinner.getSelectedItem().toString().replace("km", "");
					memberList = requestGson.getMemberGsonBySendingAPI(mContext, "/aroundUser", "GET","?lat=" + latitude.toString() + "&lng=" + longitude.toString() + "&range=" + range + "&bizType=" + bizType);
				} else {
					memberList = null;
				}
			}

			public void onThreadEnd() {
				if(memberList==null){
					Toast.makeText(mContext, "주변 동문 목록을 가져오는데 실패했습니다. 다시 시도해주세요", Toast.LENGTH_LONG).show();
				} else if(memberList.getResultCode().equals(ResultCode.SUCCESS)) {
					Toast.makeText(mContext, rangeSpinner.getSelectedItem() + " 내에 " + memberList.getItemCount().toString() + "명의 동문이 있습니다.", Toast.LENGTH_LONG).show();
					setFriendsOnMap();
					setFriendsOnList();
				}
			}
		};
		ThreadTask task = new ThreadTask((Activity)mContext, threadInterface);
		task.execute();
	}
		
	private void setFriendsOnMap(){
		int markerId = NMapPOIflagType.PIN;
		NMapPOIdata poiData = new NMapPOIdata(0, mMapViewerResourceProvider);
		
		double[] latitude = new double[memberList.getItemCount()];
		double[] longitude = new double[memberList.getItemCount()];
		String[] poiname = new String[memberList.getItemCount()];
		
		int count = 0;
		for (int i = 0; i < memberList.getItemCount(); i++) {
			latitude[count] = memberList.getList().get(i).getLatitude().doubleValue();
			longitude[count] = memberList.getList().get(i).getLongitude().doubleValue();
			poiname[count] = memberList.getList().get(i).getGraduation().toString() + "기 "+ memberList.getList().get(i).getUsername()+ " "	+ memberList.getList().get(i).getBizName();
			count++;
		}
		
		poiData.beginPOIdata(count);
		for (int j = 0; j < count; j++) {
			poiData.addPOIitem(longitude[j], latitude[j], poiname[j], markerId,	0);
		}
		poiData.endPOIdata();
		mOverlayManager.clearOverlays();
		mOverlayManager.populate();
		NMapPOIdataOverlay poiDataOverlay = mOverlayManager.createPOIdataOverlay(poiData, null);
		poiDataOverlay.setOnStateChangeListener(this);
		//poiDataOverlay.showAllPOIdata(0);
	}
	
	private void setFriendsOnList(){
		ArrayAdapter<MemberListItem> aroundListAdapter = new FindListAdapter(Tab_FindActivity.this, R.layout.listitem_findlist, (ArrayList<MemberListItem>) memberList.getList());
		aroundList.setAdapter(aroundListAdapter);
	}
	
	private void Initialize() {
		userid = mSessionManager.getUserid();

		toggleListMapBt = (Button) findViewById(R.id.tabfind_listbt);
		if (toggleFlag.equals(ResultCode.TOGGLE_MAP) == true) {
			toggleListMapBt.setText("List");
			aroundList.setVisibility(View.INVISIBLE);
			mMapView.setVisibility(View.VISIBLE);
		} else if (toggleFlag.equals(ResultCode.TOGGLE_LIST) == true) {
			toggleListMapBt.setText("MAP");
			aroundList.setVisibility(View.VISIBLE);
			mMapView.setVisibility(View.INVISIBLE);
		}

		toggleListMapBt.setOnClickListener(this);
	}
	
	private void startMyLocation() {
		Log.i(LOG_TAG, "startMyLocation");
		if (mMyLocationOverlay != null) {
			if (!mOverlayManager.hasOverlay(mMyLocationOverlay)) {
				mOverlayManager.addOverlay(mMyLocationOverlay);
			}

			if (mMapLocationManager.isMyLocationEnabled()) {
				mMapView.postInvalidate();
			} else {
				boolean isMyLocationEnabled = mMapLocationManager.enableMyLocation(false);
				if (!isMyLocationEnabled) {
					Toast.makeText(this, "Please enable a My Location source in system settings", Toast.LENGTH_LONG).show();
					mMapController.setMapCenter(NMAP_LOCATION_DEFAULT, mZoomLevel);
					return;
				}
			}
		}
	}

	private void stopMyLocation() {
		Log.i(LOG_TAG, "stopMyLocation");
		if (mMyLocationOverlay != null) {
			mMapLocationManager.disableMyLocation();
			mOverlayManager.removeOverlay(mMyLocationOverlay);
		}
	}
	
	//----------------------------------------------- below functions are listener -------------------------------------------------
	public void onClick(View v) {
		// TODO Auto-generated method stub
		if (v.getId() == toggleListMapBt.getId()) {
			if (toggleFlag.equals(ResultCode.TOGGLE_MAP) == true) {
				toggleFlag = ResultCode.TOGGLE_LIST;
				toggleListMapBt.setText("List");
				aroundList.setVisibility(View.INVISIBLE);
				mMapView.setVisibility(View.VISIBLE);
			} else if (toggleFlag.equals(ResultCode.TOGGLE_LIST) == true) {
				toggleFlag = ResultCode.TOGGLE_MAP;
				toggleListMapBt.setText("Map");
				aroundList.setVisibility(View.VISIBLE);
				mMapView.setVisibility(View.INVISIBLE);
			}
			Initialize();
		}
	}
	
	public void onItemSelected(AdapterView<?> parent, View view, int position,
			long id) {
		if (parent.getId() == biztypeSpinner.getId()) {
			biztypeSpinnerPosition = position;
			biztypeSpinner.setSelection(biztypeSpinnerPosition);
			setAroundList();
		} else if (parent.getId() == rangeSpinner.getId()) {
			rangeSpinnerPosition = position;
			rangeSpinner.setSelection(rangeSpinnerPosition);
			setAroundList();
		}
	}

	public void onNothingSelected(AdapterView<?> parent) {
	}

	public void onAnimationStateChange(NMapView arg0, int arg1, int arg2) {
	}

	public void onMapCenterChange(NMapView arg0, NGeoPoint arg1) {
	}

	public void onMapCenterChangeFine(NMapView arg0) {
	}

	public void onMapInitHandler(NMapView mapview, NMapError errorInfo) {
		if (errorInfo == null) { // success
			startMyLocation();
		} else { // fail
			Log.e(LOG_TAG, "onMapInitHandler : " + errorInfo.toString());
			Toast.makeText(this, errorInfo.toString(), Toast.LENGTH_LONG).show();
		}
	}

	public void onZoomLevelChange(NMapView arg0, int arg1) {
	}

	public boolean onLocationChanged(NMapLocationManager locationManager, NGeoPoint myLocation) {
		Log.i(LOG_TAG, "onLocationChanged");
		if (mMapController != null) {
			mMapController.setMapCenter(myLocation);
			mMapController.animateTo(myLocation);
		}
		return true;
	}

	public void onLocationUnavailableArea(NMapLocationManager locationManager, NGeoPoint myLocation) {
		Toast.makeText(Tab_FindActivity.this, "Your current location is unavailable area.",	Toast.LENGTH_LONG).show();
	}

	public void onLocationUpdateTimeout(NMapLocationManager locationManager) {
		Toast.makeText(Tab_FindActivity.this, "Your current location is temporarily unavailable.", Toast.LENGTH_LONG).show();
	}

	public NMapCalloutOverlay onCreateCalloutOverlay(NMapOverlay itemOverlay, NMapOverlayItem overlayItem, Rect itemBounds) {
		// handle overlapped items
		if (itemOverlay instanceof NMapPOIdataOverlay) {
			NMapPOIdataOverlay poiDataOverlay = (NMapPOIdataOverlay) itemOverlay;

			// check if it is selected by touch event
			if (!poiDataOverlay.isFocusedBySelectItem()) {
				int countOfOverlappedItems = 1;

				NMapPOIdata poiData = poiDataOverlay.getPOIdata();
				for (int i = 0; i < poiData.count(); i++) {
					NMapPOIitem poiItem = poiData.getPOIitem(i);

					// skip selected item
					if (poiItem == overlayItem) {
						continue;
					}

					// check if overlapped or not
					if (Rect.intersects(poiItem.getBoundsInScreen(), overlayItem.getBoundsInScreen())) {
						countOfOverlappedItems++;
					}
				}

				if (countOfOverlappedItems > 1) {
					String text = countOfOverlappedItems+ " overlapped items for " + overlayItem.getTitle();
					Toast.makeText(this, text, Toast.LENGTH_LONG).show();
					return null;
				}
			}
		}

		// use custom callout overlay
		return new NMapCalloutCustomOverlay(itemOverlay, overlayItem, itemBounds, mMapViewerResourceProvider);
	}
	
	public boolean isLocationTracking() {
		if (mMapLocationManager != null) {
			 if (mMapLocationManager.isMyLocationEnabled()) {
				 return mMapLocationManager.isMyLocationFixed();
			 }
		}
		return false;
	}

	public void onCalloutClick(NMapPOIdataOverlay dataOverlay, NMapPOIitem item) {
		int position = dataOverlay.getPOIdata().indexOf(item);
		Intent intent = new Intent(this, MemberDetailActivity.class);
		intent.putExtra("userid", userid);
		intent.putExtra("favoriteid", memberList.getList().get(position).getUserid());
		startActivity(intent);
	}

	public void onFocusChanged(NMapPOIdataOverlay arg0, NMapPOIitem arg1) {
	}
}